/*
 * sr.h - EnCluster Standard Representation structure and definitions
 * Clunix, glory@clunix.com, yjlee@clunix.com, 2001.6.5,19,7.2,11.29.
 * Clunix, cezanne@clunix.com, 2005
 *
 * Copyright (c) 2001-2005 by Clunix Inc. All Rights Reserved.
 */

#ifndef _SR_H_
#define _SR_H_

#include <stdarg.h>

#include "../libbase/ecm.h"

#include "libsr.h"
#include "sr_type.h"

/* Directory separator definitions */
#define SR_DIR_SEP      '/'
#define SR_DIR_SEP_STR  "/"

#ifdef __cplusplus
extern "C" {
#endif

#define srv_head	srv.child_head
#define srv_val		srv.val
#define srv_ival	srv.val.ival
#define srv_lval	srv.val.lval
#define srv_dval	srv.val.dval
#define srv_str		srv.val.str
#define srv_octsize	srv.val.oct.size
#define srv_octdata	srv.val.oct.data
#define srv_ptr		srv.val.ptr
#define srv_bval	srv.val.bval
#define srv_dir		srv.val.dir

typedef union {
	sr_val_t	val;
	struct list_head	child_head;
} srv_t;

#define SR_MAGIC	0xef093715
#define SR_FREED_MAGIC	0x153709ef

struct _sr_t {
#ifdef ECM_DEBUG
	ecm_uint32	magic;
#endif
	int	type;
	char	*name;		/* may be null */
	srv_t	srv;
	struct _sr_t	*parent;
	struct list_head	list;
	sr_t	*sr_ext;
};

typedef enum {
	LNI_TYPE_NONE = 0,
	LNI_TYPE_NAME,
	LNI_TYPE_ALL,
	LNI_TYPE_ANY,
	LNI_TYPE_DOT,
	LNI_TYPE_DOTDOT
} LNI_type_t;

#define ST_LNITYPE	SR_BUILD_TYPE(SR_TYPECLS_INT, 2)

extern const sr_t	SR_NULL;

typedef ECMBOOL (*sr_travfunc_t)(const sr_t *, ecm_ptr_t ctx, ECMBOOL is_last);

typedef int	sr_travopt_t;

#define SR_TRAV_GETPARENT		0x00001
#define SR_TRAV_CREATE			0x00002
#define SR_TRAV_NO_DEREF		0x00004
#define SR_TRAV_EXCEPTLAST		0x00008
#define SR_TRAV_EXIST			0x00010

#define SR_TRAV_CHILDSEL_MASK		0x00f00

#define SR_TRAV_ANY			0x00000
#define SR_TRAV_DIRONLY			0x00100
#define SR_TRAV_ABSENTONLY		0x00200	

sr_t *asr_to_sr(char **pasr);
ECM_INLINE void sr_to_asr(char **pasr, const sr_t *sr);

void srv_to_asrv(char **pasrv, srt_t srt, sr_val_t srv);

ECMBOOL search_srt(const char *srt_str, srt_t *psrt);

const char *srt_get_name(srt_t srt);
const sr_type_t *srt_get_info(srt_t srt);

sr_t *sr_get_sibling(const sr_t *sr, const char *name);

char *sr_get_LNP(const sr_t *sr);
char *sr_get_relLNP(const sr_t *sr_pivot, const sr_t *sr);
sr_t *sr_get_sr_LNP(const sr_t *sr);
sr_t *sr_get_sr_relLNP(const sr_t *sr_pivot, const sr_t *sr);

sr_t *get_sr_LNP(const char *LNPstr);
sr_t *getf_sr_LNP(const char *format, ...);
sr_t *getv_sr_LNP(const char *format, va_list ap);

char *string_LNP(const sr_t *sr_LNP);

/* sr_t *lookup_sr(const sr_t *sr_dir, const char *LN, sr_travopt_t opt); */
sr_t *traverse_sr(const sr_t *sr_dir, const sr_t *sr_LNP, sr_travfunc_t travfunc, ecm_ptr_t ctx, sr_travopt_t opt);
sr_t *traverse_sr_1(const sr_t *sr_dir, const sr_t *sr_LNP, sr_travopt_t opt);
sr_t *sr_traverse(const sr_t *sr_dir, const char *LN, sr_travfunc_t travfunc, ecm_ptr_t ctx, sr_travopt_t opt);
sr_t *sr_traverse_1(const sr_t *sr_dir, const char *LN, sr_travopt_t opt);

sr_t *grep_sr_LNP(const char *LNPstr, char **endptr);
sr_t *grepf_sr_LNP(const char *format, char **endptr, ...);
sr_t *grepv_sr_LNP(const char *format, char **endptr, va_list ap);

ecm_ptr_t sr_hashtable_get(const sr_t *sr, ecm_hashtable_t ht);
ECMBOOL sr_hashtable_insert(const sr_t *sr, ecm_hashtable_t ht, ecm_ptr_t p_entry_data);
ecm_ptr_t sr_hashtable_remove(const sr_t *sr, ecm_hashtable_t ht);
ecm_ptr_t sr_hashtable_first(ecm_hashtable_t ht, ecm_ht_iterator_t *p_iterator, sr_t **psr);
ecm_ptr_t sr_hashtable_next(ecm_hashtable_t ht, ecm_ht_iterator_t *p_iterator, sr_t **psr);

int get_LNI_idx(const sr_t *sr_LNP, int start, LNI_type_t type, const char *name);
ECMBOOL get_LNI_type(const sr_t *sr_LNP, ecm_uint32 idx, LNI_type_t *ptype, const char **pname);
sr_t *append_sr_LNP(const sr_t *sr_LNP, const sr_t *sr_appended);
void insert_LNI(sr_t *sr_LNP, int idx, LNI_type_t type, const char *name);
sr_t *get_sr_sub_LNP(const sr_t *sr_LNP, int start, int end);
void del_sr_sub_LNP(sr_t *sr_LNP, int start, int end);
ECMBOOL is_ref_sr_LNP(const sr_t *sr_LNP);
ECMBOOL is_ABS_sr_LNP(const sr_t *sr_LNP);
void set_ref_sr_LNP(sr_t *sr_LNP, ECMBOOL is_ref);
void set_ABS_sr_LNP(sr_t *sr_LNP, ECMBOOL is_ABS);
int get_LNI_count(const sr_t *sr_LNP);
sr_t *get_dir_sr_LNP(sr_t *sr_LNP);
const char *get_sr_LNP_basename(sr_t *sr_LNP);
ECMBOOL is_valid_LNP(const char *LNP);

int srt_LNP_print(srt_t srt, char *buf, ecm_size_t *pbuflen, sr_val_t srv);
ECMBOOL srt_LNP_scan(srt_t srt, char *asrv, sr_val_t *psrv);

void srv_init(srt_t srt, sr_val_t *pval);

ECMBOOL sr_is_same(const sr_t *sr1, const sr_t *sr2);

sr_t *sr_get_real(const sr_t *sr_vir);
sr_t *sr_get_real_free(const sr_t *sr_vir);

sr_t *asr_create_ASRT(char *name, ECMBOOL is_HMS, ECMBOOL is_ref);
sr_t *asr_create_ASR(char *name, sr_t *sr_srt, sr_t *sr_asrv, sr_t *sr_ext);

void sr_merge_force(sr_t *sr_group, sr_t *sr_merged);
sr_t *sr_add_idx_force(sr_t *sr_group, int idx, sr_t *sr_mbr);

#ifdef ECM_DEBUG

#define SR_DBG_BISON	1
#define SR_DBG_FLEX	2

extern ECMBOOL	sr_debug_flex;

#define SR_CHECK(sr)	if (sr) ECMASSERT(sr->magic == SR_MAGIC)
#define SR_DEBUG_FLEX(scanner)	do { srpset_debug(sr_debug_flex, scanner); } while(0)

void sr_set_debugset(int dbgset);

sr_t *edbd_sr_get_real_assert(const sr_t *sr_vir);

#define SR_APPEND_ASSERT(group, mbr)	ECMASSERT(sr_append(group, mbr) != NULL)
#define SR_APPEND_UNIQUE_ASSERT(group, mbr)	\
		ECMASSERT(sr_append_unique(group, mbr) != NULL)
#define SR_GET_REAL_ASSERT(sr)		sr_get_real_assert
#define SR_UPCAST_VHMS_ASSERT(sr, srt)	ECMASSERT(sr_upcast_vHMS(sr, srt) != NULL)

#else

#define SR_CHECK(sr)	do {} while(0)
#define SR_DEBUG_FLEX(scanner)	do { } while(0)

#define SR_APPEND_ASSERT(group, mbr)	sr_append(group, mbr)
#define SR_APPEND_UNIQUE_ASSERT(group, mbr)	sr_append_unique(group, mbr)
#define SR_GET_REAL_ASSERT(sr)		sr_get_real
#define SR_UPCAST_VHMS_ASSERT(sr, srt)	sr_upcast_vHMS(sr, srt)

#endif

#ifdef __cplusplus
}
#endif

#endif	/* SR_H */
